package com.cskaoyan.javase.oop1._11static._5exercise;

/**
 * 读程序题
 *
 * 首先启动main方法,触发Demo类的类加载
 * 于是要执行静态成员变量的显式赋值
 * 从方法栈帧上来说,就是Demo类的clinit方法栈帧进栈
 *
 * 类加载的连环触发
 * 在类加载某个类的过程中,也就是该类clinit方法执行的过程中
 * 如果碰到了其他类的类加载时机
 * 就会连环触发类加载
 * 表现为该类的clinit方法栈帧进栈
 *
 * 也就是说连环触发类加载时,最先开始类加载的类需要等待后开始类加载的类完成类加载,最先开始类加载的类最后完成类加载,最后开始类加载的类最先完成类加载(由JVM栈的先进后出保证)
 *
 * 程序的输出是:
 *      Dog
 *      Cat
 *      (以上是类加载过程中的输出,在main方法启动之前的输出)
 *      (以下是main方法执行过程中输出,而且三个类都已经类加载了,无需再次考虑类加载)
 *      hello world!
 *      Dog
 *      Demo
 *
 *
 * @since 16:11
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    /*
        和static int a = 10;没有本质区别
        但是这里创建了对象
        于是要进行Cat类的类加载
      */
    static Cat cat = new Cat();
    Dog dog = new Dog();
    Dog dog2;
    static Dog dog3;

    public static void main(String[] args) {
        System.out.println("hello world!");
        Demo d = new Demo();
    }

    public Demo() {
        System.out.println("demo");
    }
}

class Cat {
    static Dog dog = new Dog();

    public Cat() {
        System.out.println("cat");
    }
}

class Dog {
    static int num = 100;
    /*
        在类加载Demo类的过程中
        在Demo类的clinit方法没有执行完的情况下
        创建Demo对象,这种做法为什么能够存在呢?

        new对象和类加载的一个关系问题,要想弄明白这些
        需要明确知道,类加载的具体流程,究竟做了什么
        所以这里先不讲,在代码块环节里我们再讲
     */
    static Demo demo = new Demo();

    public Dog() {
        System.out.println("dog");
    }
}

class A {
    // A a = new A();
    static A a = new A();
}